package cate.common.table;

import easy.java.practice.errorcode.EcException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

@SuppressWarnings("unchecked")
@Slf4j
public abstract class ESheet<R extends ERow> {

    /** 表头所占的行数(不能改，约定为一行！) */
    protected static final int HEADER_LINES = 1;

    /** 所归属的excel */
    public EExcel parent;

    public EContext getContext() {
        return this.parent.getContext();
    }

    /** sheet名 */
    abstract public String getSheetName();

    public List<R> list;
    public Map<Integer, R> map;

    public List<R> getList() {
        if(list == null) {
            list = new ArrayList<>();
        }
        return list;
    }

    /** 通过id获取模板数据 */
    public R get(Integer id) {
        if (map == null) {
            return null;
        }
        return map.get(id);
    }

    public Class<?> getRowClass() {
        return buildRow().getClass();
    }

    protected R buildRow(){
        Type superclass = getClass().getGenericSuperclass();
        ParameterizedType parameterizedType;
        if (superclass instanceof ParameterizedType) {
            parameterizedType = (ParameterizedType) superclass;
            Type[] typeArray = parameterizedType.getActualTypeArguments();
            if (typeArray != null && typeArray.length > 0) {
                Class<R> clazz = (Class<R>) typeArray[0];
                try{
                    return clazz.getDeclaredConstructor().newInstance();
                }catch(Exception e){
                    log.error("生成{}实例失败",clazz.getName(),e);
                }
            }
        }
        return null;
    }

    public Object[] headerValues;
    private Map<String, Integer> fieldIndexMap;
    public Integer getFieldIndex(String fieldName) {
        return fieldIndexMap.get(fieldName);
    }

    /** 加载配置表 */
    public void load(XSSFSheet xs) {
        List<R> listNew = new ArrayList<>();
        Map<Integer, R> mapNew = new HashMap<>();

        fieldIndexMap = new HashMap<>();
        XSSFRow headerRow = xs.getRow(0);
        final int beg = headerRow.getFirstCellNum();
        final int end = headerRow.getLastCellNum();
        headerValues = new String[end];
        for(int i = beg; i < end; i++) {
            XSSFCell cell = headerRow.getCell(i);
            if(cell == null) {
                headerValues[i] = null;
                continue;
            }
            String cellVal = cell.getStringCellValue().replace("*", "");
            headerValues[i] = cellVal;
            if (!cellVal.isEmpty() && !cellVal.contains("备注") && !cellVal.contains("注释")) {
                if (fieldIndexMap.containsKey(cellVal)) {
                    getContext().warningOnSheetLoading(parent.getFileName(), getSheetName(), "重复的列名! [" + cellVal + "]");
                }
            }
            fieldIndexMap.put(cellVal, i);
        }

        for (int i = xs.getFirstRowNum() + HEADER_LINES; i < xs.getLastRowNum() + HEADER_LINES; i++) {
            XSSFRow xssfRow = xs.getRow(i);
            if(xssfRow == null) {
                continue;
            }

            if(i == xs.getFirstRowNum() + HEADER_LINES) {
                try {
                    XSSFCell cell = xssfRow.getCell(xssfRow.getFirstCellNum());
                    if(cell != null && cell.getCellType() == CellType.STRING) {
                        String testMark = cell.getStringCellValue();
                        if(StringUtils.isNotBlank(testMark) && StringUtils.startsWith(testMark, "#")) {
                            continue;
                        }
                    }
                } catch (Exception e) {
                    log.error("", e);
                }
            }

            XSSFRowWrap xrw = new XSSFRowWrap(xssfRow, fieldIndexMap);
            boolean allColNull = true;//所有列都是空
            for(String key : fieldIndexMap.keySet()) {
                int index = fieldIndexMap.get(key);
                XSSFCell cell = xssfRow.getCell(index);
                if(cell == null) {
                    continue;
                }
                String raw = cell.getRawValue();
                if(!StringUtils.isBlank(raw)) {
                    allColNull = false;
                    break;
                }
            }
            if(allColNull) {
                continue;
            }
            String deletedMark = xrw.getString("deleted");
            if (deletedMark != null && deletedMark.equals("1")) {
                continue;
            }
            R r = buildRow();
            r.parent = this;
            r.parseAnno(xrw);
            r.parse(xrw);
            if(r.available()) {
                // 做一下重复性检查
                R old = mapNew.get(r.id);
                if(old != null) {
                    this.parent.getContext().warningOnSheetLoading( getSheetName(), "ID= "+r.id+ "重复了");
                }
                //
                onRowCreated(r);
                r.parent = this;
                listNew.add(r);
                mapNew.put(r.id, r);
            }
        }
        list = listNew;
        map = mapNew;
        if (getClass().getAnnotation(UnuseDefaultMap.class) != null) {
            map = null;
        }
    }

    public void load(List<XSSFRawRowWrap> rawRows) {
        if (rawRows == null || rawRows.isEmpty()) {
            return;
        }
        List<R> listNew = new ArrayList<>();
        Map<Integer, R> mapNew = new HashMap<>();
        for (XSSFRawRowWrap xrw : rawRows) {
            if (xrw.isAllValueEmpty()) {
                continue;
            }
            String deletedMark = xrw.getString("deleted");
            if (deletedMark != null && deletedMark.equals("1")) {
                continue;
            }
            R r = buildRow();
            r.parent = this;
            r.parseAnno(xrw);
            r.parse(xrw);
            if(r.available()) {
                // 做一下重复性检查
                R old = mapNew.get(r.id);
                if(old != null) {
                    this.parent.getContext().warningOnSheetLoading( getSheetName(), "ID= "+r.id+ "重复了");
                }
                onRowCreated(r);
                r.parent = this;
                listNew.add(r);
                mapNew.put(r.id, r);
            }
        }
        list = listNew;
        map = mapNew;
    }

    public void onRowCreated2(R row) {
        this.onRowCreated(row);
    }

    /** 当row创建完之后 */
    protected void onRowCreated(R row) {

    }

    /** 加载完之后 */
    protected void onLoaded() {

    }

    /** 解码所有row */
    public void decode() {
        for(R row : getList()) {
            row.decode();
        }
        this.onLoaded();
    }


    public boolean create(R row) {
        R old = map.get(row.id);
        if(old != null) {
            throw new EcException("" + getSheetName() + " 中 ID= "+row.id+ "已存在");
        }
        getList().add(row);
        map.put(row.id, row);
        row.parent = this;
        return true;
    }

    public boolean update(int id, R row) {
        R old = map.get(id);
        if(old == null) {
            throw new EcException("ID=" + row.id + "未找到");
        }
        int index = -1;
        for(int i = 0; i < getList().size(); i++) {
            if(getList().get(i).id == id) {
                index = i;
                break;
            }
        }
        if(index == -1) {
            return false;
        }
        list.set(index, row);
        map.put(id, row);
        row.parent = this;
        return true;
    }

    public boolean delete(int id) {
        getList().removeIf(row -> row.id == id);
        map.remove(id);
        return true;
    }

    public String location() {
        try {
            return "" + this.parent.getFileName() + "/" + this.getSheetName();
        } catch (Exception e) {
            return ""+e.getMessage();
        }
    }
}
